//
//  String+JJExtension.swift
//  JJToolSwift
//
//  Created by heihei on 2024/5/8.
//

import Foundation

public extension String {
    
    /// 将字符串转换成url
    /// - Returns: 返回url
    func toURL() -> URL? {
        return URL(string: self)
    }
    
    /// 整合字符串
    /// - Returns: 返回string
    func trim() -> String {
        return self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    
    /// range转换为NSRange
    func nsRange(from range: Range<String.Index>) -> NSRange {
        return NSRange(range, in: self)
    }

    /// NSRange转化为range
    func range(from nsRange: NSRange) -> Range<String.Index>? {
        guard
            let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
            let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
            let fromIndex = String.Index(from16, within: self),
            let toIndex = String.Index(to16, within: self)
            else { return nil }
        return fromIndex ..< toIndex
    }
    
    /// 获取所有包含的range
    /// - Parameter string: 搜索字段
    /// - Returns: 返回数组
    func rangesFromString(string: String) -> [Range<String.Index>]? {
        let tempStr = self.lowercased()
        let searchStr = string.lowercased()
        if #available(iOS 16.0, *) {
            return tempStr.ranges(of: searchStr)
        } else {
            var list: [Range<String.Index>] = []
            guard tempStr.contains(searchStr) else {
                // 不包含字段
                return nil
            }
            var start = tempStr.startIndex
            while let range = tempStr.range(of: searchStr, options: .literal, range: start..<tempStr.endIndex),
                  !range.isEmpty {
                list.append(range)
                start = range.upperBound
            }
            return list
        }
    }
    
    /// 正则表达式匹配，能匹配到就返回true否则false
    ///
    /// - Parameters:
    ///   - regex: 正则表达式
    ///   - options: 匹配规则
    /// - Returns: true/false
    func matches(regex: String, options: NSRegularExpression.Options) -> Bool {
        if let pattern = try? NSRegularExpression(pattern: regex, options: options) {
            return (pattern.numberOfMatches(in: self, options: .reportCompletion, range: NSRange(location: 0, length: self.count)) > 0)
        } else {
            return false
        }
    }
    
    /// 将json字符串转换成字典
    /// - Returns: 返回字典
    func toDictionary() -> [String: Any]? {
        guard let data = self.data(using: .utf8), let dict = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] else {
            return nil
        }
        return dict
    }
    
    /// 复制到粘贴板
    func copyToClipboard() {
        if self.isEmpty {
            JJHUD.show(status: .warn, text: "内容为空")
            return
        }
        UIPasteboard.general.string = self
        JJHUD.show(status: .messageNoPict, text: "已复制到粘贴板")
    }
    
    /// 判断是否是有效的URL字符串
    ///
    /// - Returns: true/false
    func isValidURL() -> Bool {
        if let url = URL(string: self), let _ = url.scheme, let _ = url.host {
            return true
        }
        return false
    }
    
    /// 获取URL路径中的参数
    ///
    /// - Returns: 参数map
    func getURLParams() -> [String: String] {
        var map: [String: String] = [:]
        if let range = self.range(of: "?") {
            self.suffix(from: range.upperBound).split(separator: "&").forEach({
                let array = $0.split(separator: "=")
                if let key = array.first, let value = array.last, !key.isEmpty {
                    map[String(key)] = String(value)
                }
            })
        }
        return map
    }
    
    /// 正则表达式替换
    ///
    /// - Parameters:
    ///   - regex: 正则表达式
    ///   - replacement: 替换为字符
    /// - Returns: 替换后的字符
    func replacing(regex: String, with replacement: String) -> String {
        if let pattern = try? NSRegularExpression(pattern: regex, options: .caseInsensitive) {
            return pattern.stringByReplacingMatches(in: self, options: .reportCompletion, range: NSRange(location: 0, length: self.count), withTemplate: replacement)
        } else {
            return self
        }
    }
    
    /// 将字符串转换成对应的VC类
    /// - Returns: 返回UIViewController类型
    func toClass() -> UIViewController.Type? {
        //1、获swift中的命名空间名
        var name = Bundle.main.object(forInfoDictionaryKey: "CFBundleExecutable") as? String
        //2、如果包名中有'-'横线这样的字符，在拿到包名后，还需要把包名的'-'转换成'_'下横线
        name = name?.replacingOccurrences(of: "-", with: "_")
        //3、拼接命名空间和类名，”包名.类名“
        let fullClassName = name! + "." + self
        //通过NSClassFromString获取到最终的类，由于NSClassFromString返回的是AnyClass，这里要转换成UIViewController.Type类型
        guard let classType = NSClassFromString(fullClassName) as? UIViewController.Type  else{
            return nil
        }
        return classType
    }
    
    /// 字符串转换成date
    /// - Parameter formatter: 转换格式
    /// - Returns: 返回date
    func toDate(formatter: String = "yyyy-MM-dd HH:mm:ss") -> Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = formatter
        if let date = dateFormatter.date(from: self) {
            return date
        }
        return nil
    }
    
    /// 将GMT时间转换成本机时间
    /// - Parameter formatter: 显示格式
    /// - Returns: 返回字符串
    func gmtDateToLocal(formatter: String = "yyyy-MM-dd HH:mm:ss") -> String {
        let dateFormatter = DateFormatter()
        if let date = dateFormatter.date(from: self) {
            dateFormatter.dateFormat = formatter
            dateFormatter.timeZone = TimeZone.current // 设置为用户的时区
            let localDateString = dateFormatter.string(from: date)
            return localDateString
        }
        return self.replacing(regex: "T", with: " ").components(separatedBy: "+").first ?? self
    }
    
    /// 截取字符串
    subscript(loc: Int) -> String {
         let startIndex = self.index(self.startIndex, offsetBy: loc)
        return String(self[startIndex..<self.endIndex])
    }

    /// 截取字符串
    subscript(loc: Int, lenth: Int) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: loc)
        let endIndex = self.index(self.startIndex, offsetBy: loc + lenth)
        return String(self[startIndex..<endIndex])
    }
    
    /// 根据字体和宽度计算文本尺寸，如果是富文本属性请用自带的api实现
    ///
    /// - Parameters:
    ///   - width: 最大宽度
    ///   - font: 字体
    /// - Returns: 文本尺寸
    func labelSize(maxWidth: CGFloat, font: UIFont) -> CGSize {
        return self.boundingRect(with: CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [.font: font], context: nil).size
    }
    
    /// 根据字符串生成二维码
    /// - Parameters:
    ///   - waterImage: 水印图片，此参数若为空则不会显示水印
    ///   - ctColor: 内容颜色
    ///   - bgColor: 背景颜色
    /// - Returns: 返回二维码图片
    func creatQRCodeImage(waterImage: UIImage? = nil, ctColor: UIColor = .black, bgColor: UIColor = .white) -> UIImage {
        // 创建过滤器
        let filter = CIFilter(name: "CIQRCodeGenerator")
        // 过滤器恢复默认
        filter?.setDefaults()
        // 将string转换成data类型
        let data = self.data(using: .utf8, allowLossyConversion: true)
        // 设置容错率
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        // 设置内容
        filter?.setValue(data, forKey: "inputMessage")
        // 获取二维码过滤器生成的二维码
        guard let image = filter?.outputImage else {
            return UIImage()
        }

        // 设置颜色过滤器
        let colorFilter = CIFilter(name: "CIFalseColor")!
        colorFilter.setDefaults()
        colorFilter.setValue(image, forKey: "inputImage")
        colorFilter.setValue(CIColor(color: ctColor), forKey: "inputColor0")
        colorFilter.setValue(CIColor(color: bgColor), forKey: "inputColor1")
        guard let colorCIImg = colorFilter.outputImage else {
            return UIImage()
        }
        // 添加颜色滤镜
        var finalImg = UIImage(ciImage: colorCIImg).scaleToSize(size: CGSize(width: 150, height: 150))

        if let currentWaterImg = waterImage {
            // 根据二维码图片设置生成水印图片rect
            let waterImageRect = getWaterImageRect(image: finalImg)
            let logoImage = currentWaterImg.scaleToSize(size: waterImageRect.size)
            // 生成水印图片 rect 从00 开始
            let finalWaterImage = logoImage.clipImageRadious(
                rect: CGRect(x: 0, y: 0, width: waterImageRect.size.width, height: waterImageRect.size.height),
                radious: 4, borderW: 2, borderColor: .white)
            // 添加水印图片
            finalImg = finalImg.addWaterImage(waterImage: finalWaterImage, rect: waterImageRect)
        }
        return finalImg
    }
    
    // 根据二维码图片设置生成水印图片rect 这里限制水印的图片为二维码的1/4
    private func getWaterImageRect(image: UIImage) -> CGRect {
        let linkSize = CGSize(width: image.size.width / 4, height: image.size.height / 4)
        let linkX = (image.size.width - linkSize.width) / 2
        let linkY = (image.size.height - linkSize.height) / 2
        return CGRect(x: linkX, y: linkY, width: linkSize.width, height: linkSize.height)
    }
}
